#include "BamReader.h"

void BamReader::respond () {
    std::cout << "I am BamReader, hear me roar!\n";

}

void BamReader::openBam(std::string filename) {
    samfile_t *fp_in = NULL;
    bam1_t *b = NULL;

    fp_in = samopen(filename.c_str(), "rb", 0);
    while(samread(fp_in, b) > 0) {
        char *name  = bam1_qname(b);
        uint8_t *qual  = bam1_qual(b);
    }
}

std::string getMD(uint8_t *aux, int l_aux) {
    int nextCharIsInt = 0;
    int nextCharIsChar = 0;
    int n;
    std::stringstream key;
    std::stringstream value;
    for(n=0;n<l_aux;n++) {
        if (nextCharIsInt) {
            nextCharIsInt = 0;
        }
        else if (nextCharIsChar) {
            if (aux[n] == 0) {
                if (key.str().compare("MD")) {
                    break;
                }
                nextCharIsChar = 0;
            }
            else {
                value << aux[n];
            }
        }
// Indicates next value is an int
        else if (aux[n] == 'C') {
            nextCharIsInt = 1;
        }
// Indicates next value is a string
        else if (aux[n] == 'Z') {
            nextCharIsChar = 1;
        }
// indicate key field
        else {
              key << aux[n];
        }
    }
    return value.str();
}

variant *getVariants(bam1_t *b)  {
    int pos = b->core.pos;
    uint32_t *cigar = bam1_cigar(b);
    variant* variants;
    std::string test = getMD(aux, (b->l_aux));

    std::cout << "MD: " << test << std::endl;

    for(int k=0;k< b->core.n_cigar;++k)
    {
        int cop = cigar[k] & BAM_CIGAR_MASK; // operation
        int cl = cigar[k] >> BAM_CIGAR_SHIFT; // length

        switch (cop) {
            case BAM_CMATCH:
                printf("M");
                printf("[%d-%d]", pos, pos + cl - 1);
                pos+=cl;
                break;

            case BAM_CHARD_CLIP:
                printf("H");
                /* printf("[%d]", pos);  // No coverage */
                /* pos is not advanced by this operation */
                break;

            case BAM_CSOFT_CLIP:
                printf("S");
                /* printf("[%d]", pos);  // No coverage */
                /* pos is not advanced by this operation */
                break;

            case BAM_CDEL:
                printf("D");
                /* printf("[%d-%d]", pos, pos + cl - 1);  // Spans positions, No Coverage */
                pos+=cl;
                break;

            case BAM_CPAD:
                printf("P");
                /* printf("[%d-%d]", pos, pos + cl - 1); // Spans positions, No Coverage */
                pos+=cl;
                break;

            case BAM_CINS:
                printf("I");
                /* printf("[%d]", pos); // Special case - adds <cl> bp "throughput", but not genomic position "coverage" */
                /* How you handle this is application dependent */
                /* pos is not advanced by this operation */
                break;

            case BAM_CREF_SKIP:
                printf("S");
                /* printf("[%d-%d]", pos, pos + cl - 1); /* Spans positions, No Coverage */
                pos+=cl;
                break;

            default:
                fprintf(stderr, "Unhandled cigar_op %d:%d\n", cop, cl);
                printf("?");
        }

    }
    printf ("\n");

}

void BamReader::testOpenBam(std::string filename) {
    samfile_t *fp_in = NULL;
    bam1_t *b = NULL;

    fp_in = samopen(filename.c_str(), "rb", 0);

    if(NULL == fp_in) {
        printf("Could not open file\n");
    }
    else {
        printf("Opening file %s\n", filename.c_str());

    }

    b = bam_init1();
    int pos=0;
    int lastpos=0;

    while(samread(fp_in, b) > 0) {
        lastpos = pos;
        pos = b->core.pos;

        if(pos != lastpos) {
            printf("tid  : %d\n",b->core.tid);
            printf("pos  : %d\n",b->core.pos);
            char *name  = bam1_qname(b);
            uint8_t *aux = bam1_aux(b);
            uint8_t *qual  = bam1_qual(b);
            uint32_t *cigar = bam1_cigar(b);

            std::cout << name << "\n";

            int n=0;
            char *qseq = (char *) malloc(b->core.l_qseq+1);
            uint8_t *s   = bam1_seq(b);
            for(n=0;n<(b->core.l_qseq);n++) {
                char v = bam1_seqi(s,n);
                qseq[n] = bam_nt16_rev_table[v];
            }
            qseq[n] = 0;

            printf("name : %s\n",name);
            printf("qseq : %s\n",qseq);
            std::cout << std::endl;


            printf("qual :");
            for(n=0;n<(b->core.l_qseq);n++) {
                printf(" %d",qual[n]);
            }
            printf("\n");


            std::cout << "Testing data: "<<(b)->data<< "\n";
            std::cout << "Testing l_qname: "<< (b)->core.l_qname<< "\n";
            std::cout << "Testing cigar\n";
            getVariants(b);

            // Test code from http://www.biostars.org/post/show/4211/c-api-for-bam-iterating-over-a-cigar-string/
            // End test code

        }
        bam_destroy1(b);
        b = bam_init1();

        //#define bam1_cigar(b) ((uint32_t*)((b)->data + (b)->core.l_qname))
    }
    bam_destroy1(b);

    samclose(fp_in);




    /*
    // This example is from something

    bam_index_t *idx;
    bam_plbuf_t *buf;

    idx = bam_index_load(filename.c_str()); // load BAM index

    if (idx == 0) {
    fprintf(stderr, "BAM indexed file is not available for \"%s\".\n",filename.c_str());
    }
    else {
    std::cout << "index found\n";
    }
     */
}


